﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;

class Tetris3
{    
    static DataForFigures figure = new DataForFigures();
    // .Number - {get/set} Number of figure.
    // .Fig    - {get} Returns current array for the figure.
    // .Rot    - {get/set} Current position/Which subarray is used.
    // .RotateNext() - Changes rotation forward.
    // .RotatePrev() - Changes rotation backward.

    static int score = 0;
    static bool timer = false;
    static bool isUp = true;
    //================================
    static char symbol = '■'; //Encoding.GetEncoding(437).GetChars(new byte[] { 219 })[0];
    static byte[] leftCorner = new byte[] { 2, 10 }; // Upper left corner (rows, columns)
    static byte[,] matrix = new byte[20, 16];  // Matrix for the game (rows, columns)
    static byte minX = leftCorner[0];
    static byte maxX = (byte)(leftCorner[0] + matrix.GetLength(0));
    static byte maxy = (byte)(leftCorner[1] + matrix.GetLength(1));

    static byte[] temp = new byte[4]; //buffer

    [STAThread]

    static void Main()
    {
        Console.Title = "Tetris v.01";
        Music sound = new Music();// Use class Music to add sound.
        int volume = 30;
        sound.Player(volume);

        byte level = 0;   // Variable to show level. Level changes at every 100 points.
        int delay = 1000;                   // Delay time
        byte[] position = new byte[4];      //X, Y; Current position

        Console.CursorVisible = false;

        //===========
        int extension = 16;// window width
        //===========
        // Changes window according to game; 

        Console.Clear();
        Console.SetWindowSize(1, 1);
        Console.SetBufferSize(leftCorner[1] * 2 + matrix.GetLength(1) + extension, leftCorner[0] + matrix.GetLength(0) + 3);
        Console.SetWindowSize(leftCorner[1] * 2 + matrix.GetLength(1) + extension, leftCorner[0] + matrix.GetLength(0) + 3);
        StartMenu();

        //===========
        //Draw the border
        Win(leftCorner[1], leftCorner[0], leftCorner[1] + matrix.GetLength(1), leftCorner[0] + matrix.GetLength(0), extension);

        DateTime startTime = DateTime.Now;
        Random random = new Random();

        byte numberFigures = 7; // How many different figures we gonna use.
        byte nextNumber = (byte)random.Next(0, numberFigures); // What`s next figure.


        while (true)
        {
            timer = false;
            figure.Number = nextNumber;                         // Choose current figure.
            nextNumber = (byte)random.Next(0, numberFigures);   // Choose next figure.
            figure.Rot = 0; // Null rotation (Some figures doesn`t have as many rotations as others)

            level = (byte)(score / 100 + 1);// Change level at every 100 points.

            if (delay > 100)                  
            {
                delay = 1000 - 100 * level;  //At every level, delay time decreases.
            }


            // Set position of current figure at the center of first row.
            position[1] = 0;   // Y
            position[0] = (byte)(matrix.GetLength(1) / 2 - figure.Fig.GetLength(1) / 2);  //X   

            // Call method to show next figure.
            PrintInfoField(nextNumber, extension, level);

            //Variable to check if the figure is still faling. If figure reach last row variable value change to false and we start with the next figure.
            isUp = true; 

            // Clean buffer.
            // Без него ако продължаваме да натискаме катопадне фигурата на земята
            // следващата ще запоне от средата
            // Върви паралелно за да не бави (дали има ефект).

            Task secondTask = Task.Factory.StartNew(() =>
            {
                while (Console.KeyAvailable)
                {
                    Console.ReadKey(true);
                }
            }
            );


            if (!(checkMove(matrix, leftCorner, position))) // Check if it`s possible to create object.
            {
                break;// end
            }
            else
            {
                PrintFig(position, leftCorner);//PrintFig current figure.
            }

            // Divide game in two - timer and controler.
            // Controler
            Task firstTask = Task.Factory.StartNew(() => Control(position, matrix, leftCorner));

            //Timer
            while (isUp)
            {
                Thread.Sleep(delay);
                timer = true;
            }
        }
        DateTime endTime = DateTime.Now;
        TimeSpan duration = endTime - startTime;
        Console.ForegroundColor = ConsoleColor.DarkBlue;
        Console.BackgroundColor = ConsoleColor.DarkYellow;
        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 - 2);
        Console.Write("GAME OVER");
        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 - 1);
        Console.WriteLine("Score: {0}", score);
        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 - 0);
        Console.WriteLine("Time: {0:mm\\:ss}", duration);
        HighScore(score);
        Console.ResetColor();
        Console.ReadLine(); // It`s used to keep window open.
    }
    static void StartMenu()
    {
        try
        {
            using (StreamReader reader = new StreamReader(@"..\..\StartMenu.txt"))
            {
                string fileContents = reader.ReadToEnd();
                Console.WriteLine(fileContents);
            }
        }
        catch (FileNotFoundException)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("StartMenu file is not found. Sorry for the inconvenience.");
            Console.WriteLine("Press enter to start playing.");
            Console.ResetColor();
        }
        catch (IOException ioex)
        {
            Console.WriteLine(ioex.Message);
        }
        catch (OutOfMemoryException oomex)
        {
            Console.WriteLine(oomex.Message);
        }
        Console.ReadLine();
        Console.Clear();
    }

    // Check if figure can be printed at given position.
    static bool checkMove(byte[,] matrix, byte[] leftCorner, byte[] position)
    {
        if (!  (//position[0] >= leftCorner[0] - 1 &&
               position[1] + figure.Fig.GetLength(0) <= matrix.GetLength(0) &&
               position[0] + figure.Fig.GetLength(1) <= matrix.GetLength(1)
               )
            )
        {
            return false;// If it`s out of range of matrix figure can`t be moved.
        }

        for (int i = 0; i < figure.Fig.GetLength(0); i++)
        {
            for (int j = 0; j < figure.Fig.GetLength(1); j++)
            {
                if (figure.Fig[i, j] == 1 && matrix[i + position[1], j + position[0]] == 1)
                {
                    return false;// Figure can`t be moved because there is other object at these position.
                }
            }
        }
        return (true);// Figure can be moved.
    }

    // Print Figure
    static void PrintFig(byte[] position, byte[] leftCorner)
    {
        for (int i = 0; i < figure.Fig.GetLength(0); i++)
        {
            for (int j = 0; j < figure.Fig.GetLength(1); j++)
            {
                Console.SetCursorPosition(position[0] + j + leftCorner[1], position[1] + i + leftCorner[0]);

                if (figure.Fig[i, j] == 1)
                {
                    Console.Write(symbol);
                }
            }
        }
    }

    //Delete Figure
    static void Clear(byte[] position, byte[] leftCorner)
    {
        Console.ForegroundColor = ConsoleColor.Black;

        for (int i = 0; i < figure.Fig.GetLength(0); i++)
        {
            for (int j = 0; j < figure.Fig.GetLength(1); j++)
            {
                Console.SetCursorPosition(position[0] + j + leftCorner[1], position[1] + i + leftCorner[0]);

                if (figure.Fig[i, j] == 1)
                {
                    Console.Write(symbol);
                }
            }
        }

        Console.ResetColor();
    }

    //Keybord control and timer
    static void Control(byte[] position, byte[,] matrix, byte[] leftCorner)
    {
        while (isUp)
        {
            ConsoleKeyInfo key;

            if (Console.KeyAvailable)
            {
                key = Console.ReadKey(true);
                switch (key.Key.ToString())
                {
                    case "UpArrow":

                        figure.RotateNext();

                        if (!checkMove(matrix, leftCorner, position))
                        {
                            figure.RotatePrev();
                        }
                        else
                        {
                            figure.RotatePrev();
                            Clear(position, leftCorner);
                            figure.RotateNext();
                            PrintFig(position, leftCorner);
                        }
                        break;

                    case "LeftArrow":

                        Array.Copy(position, temp, position.Length);
                        temp[0]--;

                        if (checkMove(matrix, leftCorner, temp))
                        {
                            Clear(position, leftCorner);
                            Array.Copy(temp, position, position.Length);
                            PrintFig(position, leftCorner);
                        }
                        break;

                    case "RightArrow":

                        Array.Copy(position, temp, position.Length);
                        temp[0]++;

                        if (checkMove(matrix, leftCorner, temp))
                        {
                            Clear(position, leftCorner);
                            Array.Copy(temp, position, position.Length);
                            PrintFig(position, leftCorner);
                        }
                        break;

                    case "DownArrow":
                        Array.Copy(position, temp, position.Length);
                        temp[1]++;

                        if (checkMove(matrix, leftCorner, temp))
                        {
                            Clear(position, leftCorner);
                            Array.Copy(temp, position, position.Length);
                            PrintFig(position, leftCorner);
                        }
                        else
                        {
                            timer = true;
                        }
                        break;

                    case "Spacebar":

                        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) + 6, 15);
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("Paused");
                        Console.ResetColor();
                        do
                        {
                            key = Console.ReadKey(true);
                            Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) + 6, 15);
                            Console.WriteLine("      ");

                        }
                        while (key.Key.ToString() != "Spacebar");
                        break;

                } //End switch
            }
            if (timer)//If there is signal from timber move or stop and get next figure.
            {
                Array.Copy(position, temp, temp.Length);
                temp[1]++;

                if (checkMove(matrix, leftCorner, temp))//Check if move is possible.
                {
                    Clear(position, leftCorner);
                    position[1]++;
                    PrintFig(position, leftCorner);
                    timer = false;
                }
                else
                {
                    WriteInMatrix(position, matrix, leftCorner);//exit
                    isUp = false;
                }
            }
        }
    }
    // Write fallen elements in matrix.
    static void WriteInMatrix(byte[] position, byte[,] matrix, byte[] leftCorner)
    {
        int posX = position[0];
        int posY = position[1];

        for (int i = 0; i < figure.Fig.GetLength(0); i++)
        {
            for (int j = 0; j < figure.Fig.GetLength(1); j++)
            {
                matrix[posY + i, posX + j] += figure.Fig[i, j];
            }
        }

        Check(position, matrix, leftCorner); //Check for full rows.
        PrintMatrix(position, matrix, leftCorner);
        Task sound = Task.Factory.StartNew(() => Console.Beep(250, 100));

    }

    static void PrintMatrix(byte[] position, byte[,] matrix, byte[] leftCorner)
    {
        Console.ForegroundColor = ConsoleColor.Red; //Change color
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            for (int j = 0; j < matrix.GetLength(1); j++)
            {
                Console.SetCursorPosition(j + leftCorner[1], i + leftCorner[0]);
                if (matrix[i, j] == 1)
                {
                    Console.Write(symbol);
                }
                else
                {
                    Console.Write(' ');
                }
            }
        }
        Console.ResetColor();
    }
    //Check for full rows.
    static void Check(byte[] position, byte[,] matrix, byte[] leftCorner)
    {
        byte sum = 0;
        List<int> listRows = new List<int>();
        Console.ForegroundColor = ConsoleColor.Yellow;

        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            sum = 0;
            for (int j = 0; j < matrix.GetLength(1); j++)
            {
                sum += matrix[i, j];
            }
            if (sum == matrix.GetLength(1))
            {

                listRows.Add(i);
                // Null row if full.
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    matrix[i, j] = 0;
                }

                //Color rows in yellow.
                Console.SetCursorPosition(leftCorner[1], i + leftCorner[0]);
                Console.WriteLine(new string(symbol, matrix.GetLength(1)));
            }
        }
        if (listRows.Count > 0) // if there is at least one symbol then we have a row.
        {
            Thread.Sleep(500);//Почивка
            ClearLine(listRows, position, matrix, leftCorner);// Delete full row from matrix.
            score += listRows.Count * listRows.Count;   // 
            //BEEP
        }
    }
    //Rearange rows.
    static void ClearLine(List<int> listRows, byte[] position, byte[,] matrix, byte[] leftCorner)
    {
        listRows.Reverse(); // Number of rows.
        byte count = 0;     // Number of rearanging rows.
        {

            for (int i = listRows[0]; i >= 0 + count; i--)
            {
                if (count < listRows.Count && i - count == listRows[count])
                {
                    while (count < listRows.Count - 1 && listRows[count] - 1 == listRows[count + 1])
                    {
                        count++;
                    }
                    count++;
                }
                if (i + count - 1 < matrix.GetLength(0)) // Премахва бъга да прескочи над матрицата 
                {
                    Console.SetCursorPosition(leftCorner[1], leftCorner[0] + i + count - 1);
                    Console.Write(new string(' ', matrix.GetLength(1)));// delete symbols.
                }
                for (int j = 0; j < matrix.GetLength(1); j++)
                {

                    matrix[i, j] = matrix[i - count, j];
                }
                PrintMatrix(position, matrix, leftCorner);// Print new matrix
                //Thread.Sleep(200);
                //Console.Beep(250, 100);
            }
        }
    }

    // Това е за тест - изписва съдържанието на матрицата някъде отдолу()
    static void PrintNumberMatrix(byte[] position, byte[,] matrix, byte[] leftCorner, byte[][][,] ob, int number)
    {
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            for (int j = 0; j < matrix.GetLength(1); j++)
            {
                Console.SetCursorPosition(j, i + 20);
                Console.Write(matrix[i, j]);
            }
        }
    }
    //Wndows around the field
    static void Win(int upLeftX, int upLeftY, int downRightX, int downRightY, int extension)
    {
        //width of addition field - row 40
        char[] chars = new char[] { '╔', '═', '╗', '║', '╚', '═', '╝', '║', '╩', '╦' };

        Console.SetCursorPosition(upLeftX - 1, upLeftY - 1);
        for (int i = upLeftX - 1; i <= downRightX; i++)
        {
            if (i == upLeftX - 1)
            {
                Console.Write(chars[0]);
            }
            else if (i < downRightX)
            {
                Console.Write(chars[1]);
            }
            else if (i == downRightX)
            {
                Console.WriteLine(chars[9]);
            }
        }
        for (int i = upLeftY - 1; i < downRightY - 1; i++)
        {
            Console.SetCursorPosition(downRightX, Console.CursorTop);
            Console.Write(chars[3]);
            Console.SetCursorPosition(upLeftX - 1, Console.CursorTop);
            Console.WriteLine(chars[3]);
        }
        Console.SetCursorPosition(upLeftX - 1, downRightY);
        for (int i = upLeftX - 1; i <= downRightX; i++)
        {
            if (i == upLeftX - 1)
            {
                Console.Write(chars[4]);
            }
            else if (i < downRightX)
            {
                Console.Write(chars[5]);
            }
            else if (i == downRightX)
            {
                Console.Write(chars[8]);
            }
        }
        //extension frame
        Console.SetCursorPosition(downRightX + 1, upLeftY - 1);
        for (int i = downRightX + 1; i <= downRightX + extension; i++)
        {
            if (i < downRightX + extension)
            {
                Console.Write(chars[1]);
            }
            else if (i == downRightX + extension)
            {
                Console.WriteLine(chars[2]);
            }
        }
        for (int i = upLeftY - 1; i < downRightY - 1; i++)
        {
            Console.SetCursorPosition(downRightX + extension, Console.CursorTop);
            Console.WriteLine(chars[3]);
        }
        Console.SetCursorPosition(downRightX + 1, downRightY);
        for (int i = downRightX + 1; i <= downRightX + extension; i++)
        {
            if (i < downRightX + extension)
            {
                Console.Write(chars[1]);
            }
            else if (i == downRightX + extension)
            {
                Console.WriteLine(chars[6]);
            }
        }

        Console.WriteLine();
    }

    // Print additional field.
    static void PrintInfoField(byte nextNumber, int extension, byte level)
    {
        // Text in additionl field
        string label = "Next: ";
        string secondLabel = "Level: ";
        string thirdLabel = "Score: ";


        byte offset = (byte)(leftCorner[1] + matrix.GetLength(1) + label.Length + 2);

        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) + 2, 5);
        Console.WriteLine(label);

        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) + 2, 7);
        Console.WriteLine("{0}{1}", secondLabel, level);

        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) + 2, 9);
        Console.WriteLine("{0}{1}", thirdLabel, score);

        Console.ForegroundColor = ConsoleColor.Yellow;
        for (int i = 0; i < 3; i++)
        {
            Console.SetCursorPosition(offset, 5 + i - 2);
            Console.WriteLine(new string(' ', 4));
        }


        for (int i = 0; i < figure.FindNext(nextNumber).GetLength(0); i++)
        {
            for (int j = 0; j < figure.FindNext(nextNumber).GetLength(1); j++)
            {
                Console.SetCursorPosition(offset + j, 5 + i - figure.FindNext(nextNumber).GetLength(0) + 1);
                if (figure.FindNext(nextNumber)[i, j] == 1)
                {
                    Console.WriteLine(symbol);
                }
            }
        }

        Console.ResetColor();
    }
    
    // Метод който приема точките от играта, чете максималните резултати от текстов файл. Method which gets score for current game read max results from text file. 
    // If current result is better asks for player name and adds result to char.
    // At the end of tha game prints results.
    // Press any key to end the game.
    // <param name="score">Резултат от играта</param>
    static void HighScore(int score)
    {
        string file = @"..\..\HighScore.txt";
        List<int> scores = new List<int>();
        List<string> names = new List<string>();
        try
        {
            StreamReader reader = new StreamReader(file);
            using (reader)
            {
                for (int lineNum = 0; lineNum < 3; lineNum++)
                {
                    string line = reader.ReadLine();
                    string pointsStr = Regex.Match(line, @"^[0-9]+").Value;
                    int points = int.Parse(pointsStr);
                    scores.Add(points);
                    string name = Regex.Match(line, "\\w+$").Value;
                    names.Add(name);
                }
            }
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine("The file with the high scores is not found.");
        }
        catch (IOException ioex)
        {
            Console.WriteLine(ioex.Message);
        }
        catch (OutOfMemoryException oomex)
        {
            Console.WriteLine(oomex.Message);
        }

        if (score >= scores[0])
        {
            SwitchPositions(scores, names, 2, 1);
            SwitchPositions(scores, names, 0, 1);
            scores[0] = score;
            names[0] = HighScoreEnterName();
            WriteScoresInFile(file, scores, names);
        }
        else if (score >= scores[1])
        {
            SwitchPositions(scores, names, 2, 1);
            scores[1] = score;
            names[1] = HighScoreEnterName();
            WriteScoresInFile(file, scores, names);
        }
        else if (score >= scores[2])
        {
            scores[2] = score;
            names[2] = HighScoreEnterName();
            WriteScoresInFile(file, scores, names);
        }
        HighScorePrint(scores, names);
    }

    /// <summary>
    /// Print highscores.
    /// </summary>
    /// <param name="scores">Highscores list</param>
    /// <param name="names">List with player names and results.</param>
    private static void HighScorePrint(List<int> scores, List<string> names)
    {
        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 + 3);
        Console.Write("HIGH SCORES:");
        for (int i = 0; i < 3; i++)
        {
            Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 + 4 + i);
            Console.Write("{0} - {1}", scores[i], names[i]);
        }
        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 + 7);
        Console.Write("Press any key to exit...");

    }

    /// <summary>
    /// Method to return player`s name.
    /// </summary>
    /// <returns>Name</returns>
    private static string HighScoreEnterName()
    {
        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 + 1);
        Console.Write("You`ve reached top three high scores!");
        Console.SetCursorPosition(leftCorner[1] + matrix.GetLength(1) / 2, leftCorner[0] + matrix.GetLength(0) / 2 + 2);
        Console.Write("Enter your name: ");
        return Console.ReadLine();
    }

    /// <summary>
    /// Method to write scores in txt file.
    /// </summary>
    /// <param name="file">File</param>
    /// <param name="scores">List with results</param>
    /// <param name="names">List with names</param>
    private static void WriteScoresInFile(string file, List<int> scores, List<string> names)
    {
        StreamWriter writer = new StreamWriter(file);
        using (writer)
        {
            for (int index = 0; index < 3; index++)
            {
                writer.WriteLine("{0} - {1}", scores[index], names[index]);
            }
        }
    }

    /// <summary>
    /// Method to replace positions.
    /// </summary>
    /// <param name="score">List with results</param>
    /// <param name="names">List with names</param>
    /// <param name="pos1">Position which must be changed.</param>
    /// <param name="pos2">New position.</param>
    static void SwitchPositions(List<int> score, List<string> names, int pos1, int pos2)
    {
        int tempScore = score[pos1];
        score[pos1] = score[pos2];
        score[pos2] = tempScore;
        string tempName = names[pos1];
        names[pos1] = names[pos2];
        names[pos2] = tempName;
    }

}
// Class to create figures.
class DataForFigures
{
    private byte number;
    private byte rot;
    private byte[][][,] data = Elements();

    public byte Number  // number of figure
    {
        get
        {
            return this.number;
        }
        set
        {
            this.number = value;
        }
    }

    public byte Rot // rotation for figures.
    {
        get
        {
            return this.rot;
        }
        set
        {
            byte buffer = value;

            if (buffer >= 0 && buffer < data[number].Length)
            {
                this.rot = buffer;
            }

        }
    }
    public byte[,] Fig  // Returnt array with current position of figure.
    //arrays are with different sizes.
    {
        get
        {
            return this.data[number][rot];
        }
    }
    static byte[][][,] Elements()
    {
        byte[][][,] elements = new byte[7][][,];

        //================== 1

        elements[0] = new byte[2][,];
        elements[0][0] = new byte[,] 
        { 

            { 1, 1, 1, 1 }

        };


        elements[0][1] = new byte[,] 
        {
            {1},
            {1},
            {1},
            {1}
        };

        //================== 2

        elements[1] = new byte[1][,];
        elements[1][0] = new byte[,]
        {
            {1,1},
            {1,1}
        };

        //================== 3

        elements[2] = new byte[2][,];
        elements[2][0] = new byte[,]
        {
            {1,1,0},
            {0,1,1},
        };
        elements[2][1] = new byte[,]
        {
            {0,1},
            {1,1},
            {1,0},
        };

        //================== 4

        elements[3] = new byte[4][,];
        elements[3][0] = new byte[,]
        {
            {0,1,0},
            {1,1,1},
        };
        elements[3][1] = new byte[,]
        {
            {1,0},
            {1,1},
            {1,0},
        };
        elements[3][2] = new byte[,]
        {
            {1,1,1},
            {0,1,0},
        };
        elements[3][3] = new byte[,]
        {
            {0,1},
            {1,1},
            {0,1},
        };
        //================== 5


        elements[4] = new byte[2][,];
        elements[4][0] = new byte[,]
        {
            {0,1,1},
            {1,1,0}
        };
        elements[4][1] = new byte[,]
        {
            {1,0},
            {1,1},
            {0,1}
        };

        //================== 6

        elements[5] = new byte[4][,];
        elements[5][0] = new byte[,]
        {
            {1,1,1},
            {1,0,0},
        };
        elements[5][1] = new byte[,]
        {
            {1,0},
            {1,0},
            {1,1},
        };
        elements[5][2] = new byte[,]
        {
            {0,0,1},
            {1,1,1},
        };
        elements[5][3] = new byte[,]
        {
            {1,1},
            {0,1},
            {0,1},
        };

        //================= 7
        elements[6] = new byte[1][,];
        elements[6][0] = new byte[,]
        {
            {1}
        };


        return elements;
    }
    public void RotateNext()  // Forward rotation.
    {
        this.rot = (byte)((this.rot + 1) % (data[number].Length));
    }

    public void RotatePrev() // Backward rotation.
    {
        if (this.rot - 1 < 0)
        {
            this.rot = (byte)(data[number].Length - 1);
        }
        else
        {
            this.rot--;
        }
    }
    public byte[,] FindNext(byte number)  // Returns array with chosen fig in standart position.
    {
        return (data[number][0]);
    }

}
//Class to add music.
class Music
{
    [DllImport("winmm.dll")]
    private static extern long mciSendString(string strCommand, StringBuilder strReturn, int iReturnLength, int bla);

    [STAThread]
    public void Player(int volume)
    {
        mciSendString("open \"" + @"..\..\TetrisMusic.mp3" + "\" type mpegvideo alias MediaFile", null, 0, 0);
        mciSendString("play MediaFile REPEAT", null, 0, 0);
        // Volume  sound
        mciSendString(string.Concat("setaudio MediaFile volume to ", volume), null, 0, 0);

        // http://www.codeproject.com/Articles/16316/Audio-Player-using-winmm-dll-and-WPL-File
    }
}

